﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace TNKDKS
{
    public class VectorGenerator
    {
        private static Random random = new Random();

        public List<BitArray> Generate(int vectorLength, int factor)
        {
            if (vectorLength == 0 || factor == 0 || factor > vectorLength)
            {
                throw new ArgumentException("Не коректно заданы входные параметры.");
            }
            List<BitArray> barr = GetVectors(vectorLength, factor);
            
            barr = ShuffleList(barr);

            switch (factor)
            {
                case 3:
                    return CutList(barr, 0.5);                       
                case 4:
                    return CutList(barr, 0.1);
                default:
                    return barr;
            }
            
        }

        private List<BitArray> GetVectors(int vectorLength, int factor)
        {
            string initialVector = GetInitialVector(vectorLength, factor);
            List<BitArray> result = new List<BitArray>();
            result.Add(ConvertFromStringToBitArray(initialVector));
            
            char[] str = initialVector.ToCharArray();
            int n = initialVector.Length - 1;
            int k = 0;
            char y;
            int t = 0;
            string tmp = string.Empty;
            while (true)
            {
                k = str.Length - 2;
                while ((k >= 0) && (str[k] >= str[k + 1]))
                {
                    k--;
                }
                if (k < 0)
                {
                    return result;
                }
                t = k + 1;
                while ((t < n) && (str[t + 1] > str[k]))
                {
                    t++;
                }
                y = str[k];
                str[k] = str[t];
                str[t] = y;
                t = 0;
                while (t < (int)((double)(n - k) / 2.0))
                {
                    y = str[n - t];
                    str[n - t] = str[k + t + 1];
                    str[k + t + 1] = y;
                    t++;
                }
                tmp = new string(str);
                result.Add(ConvertFromStringToBitArray(tmp));
            }
        }

        private BitArray ConvertFromStringToBitArray(string str)
        {
            BitArray barr = new BitArray(str.Length);
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == '0')
                {
                    barr[i] = false;
                }
                else
                {
                    barr[i] = true;
                }
            }
            return barr;
        }

        private string GetInitialVector(int vectorLength, int factor)
        {
            StringBuilder strBuilder = new StringBuilder(vectorLength);
            for (int i = 0; i < factor; i++)
            {
                strBuilder.Append("0");
            }
            for (int i = 0; i < vectorLength - factor; i++)
            {
                strBuilder.Append("1");
            }
            return strBuilder.ToString();
        }

        private List<BitArray> ShuffleList(List<BitArray> list)
        {
            BitArray[] arr = new BitArray[list.Count];
            list.CopyTo(arr);
            byte[] keys = new byte[arr.Length];
            random.NextBytes(keys);
            Array.Sort(keys, arr);
            return new List<BitArray>(arr);
        }

        private List<BitArray> CutList(List<BitArray> barr, double percents)
        {
            int newLength = (int)(barr.Count * percents);
            List<BitArray> result = new List<BitArray>(newLength);
            for (int i = 0; i < newLength; i++)
            {
                result.Add(barr[i]);
            }
            return result;
        }
    }
}
